Using TensorFlow

build Tensor
import tensorflow as tf
import numpy as np
np.set_printoptions(precision=3)
a=np.array([1, 2, 3], dtype=np.int32)
b=[4, 5, 6]
t_a=tf.convert_to_tensor(a)
t_b=tf.convert_to_tensor(b)
print(t_a)
print(t_b)

tf.Tensor([1 2 3], shape=(3,), dtype=int32)

tf.Tensor([4 5 6], shape=(3,), dtype=int32)

t_ones=tf.ones((2, 3))
t_ones.shape

TensorShape([2, 3])

Tensor가 참조하는 값 얻기, numpy()
t_ones.numpy()

array([[1., 1., 1.],

       [1., 1., 1.]], dtype=float32)

import numpy as np
const_tensor=tf.constant([1.2, 5, np.pi], dtype=tf.float32)
print(const_tensor)

tf.Tensor([1.2       5.        3.1415927], shape=(3,), dtype=float32)

tf.convert_to_tensor() 는 tf.constant()와 달리 tf.Variable객체도 입력받을 수 있다.(tf.fill(), tf.one_hot() 도 가능)
tf.fill()
tf.fill((2, 3), 1)

<tf.Tensor: shape=(2, 3), dtype=int32, numpy=

array([[1, 1, 1],

       [1, 1, 1]], dtype=int32)>

tf.one_hot() 원-핫 인코딩 행렬을 생성
tf.one_hot([0, 1, 2], 4)

array([[1., 0., 0., 0.],

       [0., 1., 0., 0.],

       [0., 0., 1., 0.]], dtype=float32)>

텐서의 데이터 타입과 크기 조작
tf.cast() 텐서의 데이터 타입을 원하는 타입으로 변경
t_a_new=tf.cast(t_a, tf.int64)
print(t_a_new)

tf.Tensor([1 2 3], shape=(3,), dtype=int64)

tf.transpose() 텐서를 전치
t=tf.random.uniform(shape=(3, 5))
t_tr=tf.transpose(t)
print(t.shape, '-->', t_tr.shape)

(3, 5) --> (5, 3)

reshape() 텐서의 크기를 변경(ex: 1D벡터에서 2D 행렬로)
t=tf.zeros((30, ))
t_reshape=tf.reshape(t, shape=(5, 6))
print(t_reshape.shape)

(5, 6)

squeeze() 불필요한 차원을 삭제(크기가 1인 차원은 불필요함)
t=tf.zeros((1, 2, 1, 4, 1))
t_sqz=tf.squeeze(t, axis=(2, 4))
print(t.shape, '-->', t_sqz.shape)

(1, 2, 1, 4, 1) --> (1, 2, 4)

텐서에 수학 연산 적용
곱셈, 행렬 곱셈, 텐서의 노름(norm) 연산 등 필요
tf.random.set_seed(1)
t1=tf.random.uniform(shape=(5, 2), minval=-1.0, maxval=1.0)
t2=tf.random.normal(shape=(5, 2), mean=0.0, stddev=1.0)
Probability Distribution – Uniform - From The GENESIS
tf.multiply() 원소별 곱셈
t3=tf.multiply(t1, t2).numpy()
print(t3)
tf.math.reduce_mean(), tf.math.reduce_sum(), tf.math.reduce_std()
특정 축(들)을 따라 평균, 합 ,표준 편차를 계산
t4=tf.math.reduce_mean(t1, axis=0)
print(t4)

tf.Tensor([0.09  0.207], shape=(2,), dtype=float32)

axis=None이 default value로 만약 None이면, 모든 차원이 축소되어 스칼라 텐서가 나온다.
(모든 값에 대한 평균, 합, 표준 편차)
tf.linalg.matmul() 행렬 곱셈(t1Xt2.T)
t5=tf.linalg.matmul(t1, t2, transpose_b=True)
t6=tf.linalg.matmul(t1, t2, transpose_a=True)
print(t5)
print()
print(t6)

[[-1.144  1.115 -0.87  -0.321  0.856]

 [ 0.248 -0.191  0.25  -0.064 -0.331]

 [-0.478  0.407 -0.436  0.022  0.527]

 [ 0.525 -0.234  0.741 -0.593 -1.194]

 [-0.099  0.26   0.125 -0.462 -0.396]], shape=(5, 5), dtype=float32)


tf.Tensor(

[[-1.711  0.302]

 [ 0.371 -1.049]], shape=(2, 2), dtype=float32)

tf.norm() 노름을 계산
norm_t1=tf.norm(t1, ord=2, axis=1).numpy()
print(norm_t1)

[1.046 0.293 0.504 0.96  0.383]

참조)
넘파이 함수는 입력 매개변수를 처리하기 전에 해당 객체의 __aray__() 메서드를 호출하여
넘파이 호환성을 가진 객체를 만들 수 있다.
ex) Pandas Series 객체를 넘파이 API에 사용할 수 있다.
텐서에서도 이와 같이 구현되어 있어서 넘파이 함수를 입력으로 사용할 수 있다.

많은 텐서플로 수학 함수는 최상위 수준에서 참조가능(중간의 math, linalg 등 생략 가능)
ex) tf.multiply(), tf.reduce_mean(), tf.reduce_sum(), tf.matmul()

파이썬 3.5부터는 아래와 같이 표기 가능
t1@tf.transpose(t2) # same as tf.matmul(t1, t2, transpose_b=True)

<tf.Tensor: shape=(5, 5), dtype=float32, numpy=

array([[-1.144,  1.115, -0.87 , -0.321,  0.856],

       [ 0.248, -0.191,  0.25 , -0.064, -0.331],

       [-0.478,  0.407, -0.436,  0.022,  0.527],

       [ 0.525, -0.234,  0.741, -0.593, -1.194],

       [-0.099,  0.26 ,  0.125, -0.462, -0.396]], dtype=float32)>

tf.experimental.numpy
텐서플로 2.4 버전부터 tf.experimental.numpy 모듈 아래에서 넘파일(ver1.15) 호환 API 제공
https://www.tensorflow.org/api_docs/python/tf/experimental/numpy
import tensorflow.experimental.numpy as tnp
tn1=tnp.array(t1)
tn2=tnp.array(t2)
print(tnp.dot(tn1, tn2.T))

ndarray<tf.Tensor(

[[-1.144  1.115 -0.87  -0.321  0.856]

 [ 0.248 -0.191  0.25  -0.064 -0.331]

 [-0.478  0.407 -0.436  0.022  0.527]

 [ 0.525 -0.234  0.741 -0.593 -1.194]

 [-0.099  0.26   0.125 -0.462 -0.396]], shape=(5, 5), dtype=float32)>

위와 같이 numpy API를 호환해서 사용가능
텐서플로 수학 함수
https://www.tensorflow.org/api_docs/python/tf/math
텐서플로 선형대수 함수
https://www.tensorflow.org/api_docs/python/tf/linalg
하나의 텐서를 여러개의 텐서로 나누는, 여러개의 텐서를 하나의 텐서로 합치는 연산
split(), stack(), concat()
tf.split() 텐서를 지정한 크기(개수)로 분할
입력된 텐서를 동일한 크기의 텐서 리스트로 분할
num_or_size_splits 매개변수는 분할할 텐서 개수
axis 매개변수로 원하는 차원을 지정
리스트로 원하는 크기 전달 가능
    분할 개수 지정하기
tf.random.set_seed(1)
t=tf.random.uniform((6, ))
print(t.numpy())

[0.165 0.901 0.631 0.435 0.292 0.643]

t_splits=tf.split(t, num_or_size_splits=3)
[item.numpy() for item in t_splits]

[array([0.165, 0.901], dtype=float32), array([0.631, 0.435], dtype=float32), array([0.292, 0.643], dtype=float32)]

    다른 분할 크기 전달하기
tf.random.set_seed(1)
t=tf.random.uniform((5, ))
print(t.numpy())
t_splits=tf.split(t, num_or_size_splits=[3, 2])
[item.numpy() for item in t_splits]

[array([0.165, 0.901, 0.631], dtype=float32), array([0.435, 0.292], dtype=float32)]

tf.concat() 여러 개의 텐서를 연결
A=tf.ones((3, ))
B=tf.zeros((2, ))
C=tf.concat([A, B], axis=0)
print(C.numpy())

[1. 1. 1. 0. 0.]

tf.stack() 여러 개의 텐서를 쌓음
A=tf.ones((3, ))
B=tf.zeros((3, ))
S=tf.stack([A, B], axis=1)
print(S.numpy())

[[1. 0.]

 [1. 0.]

 [1. 0.]]